#include "stdafx.h"
#include "ItemsModel.h"
#include "Strings.h"
#include <assert.h>
#include "Item.h"

ItemsModel::ItemsModel(size_t bucket_size, QObject *parent)
    : QAbstractListModel(parent), _items(std::unordered_map<unsigned long long, Item>(bucket_size))
{
}
ItemsModel::ItemsModel(QObject *parent)
    : QAbstractListModel(parent)
{
}

ItemsModel::~ItemsModel()
{

}

Item ItemsModel::pickFromThisWhichNotCollide(const ItemsModel *other) const
{
    for (auto p : this->_items)
    {
        if (!other->existId(p.first))
            return p.second;
    }
    throw "pickNotCollision : All items collide!";
}

void ItemsModel::add(const Item& item)
{
    assert(!exist(item));

    auto index = _items.size();
    QAbstractListModel::beginInsertRows(QModelIndex(), index, index);
    _items.emplace(idOf(item), item);
    QAbstractListModel::endInsertRows();
}

void ItemsModel::update(const Item &item)
{
    assert(exist(item));

    _items.at(idOf(item)) = item;
}

void ItemsModel::remove(const Item& item)
{
    auto id = idOf(item);
    auto index = indexOf(item);
    QAbstractListModel::beginInsertRows(QModelIndex(), index, index);
    _items.erase(_items.lower_bound(id));
    QAbstractListModel::endInsertRows();
}

void ItemsModel::clear()
{
    _items.clear();
}

int ItemsModel::size() const
{
    return _items.size();
}

bool ItemsModel::exist(const Item& item) const
{
    return _items.count(idOf(item)) > 0;
}

bool ItemsModel::existId(unsigned long long id) const
{
    return _items.count(id) > 0;
}

const Item &ItemsModel::item(unsigned long long id) const
{
    return _items.at(id);
}

//Item ItemsModel::toMap() const
//{
//    QVariantMap o;
//    auto copy = this->_items;
//    int i = 0;
//    for (auto it = _items.cbegin(), e = _items.cend();
//        it != e;
//        it++)
//    {
//        auto item = it->second;
//        o[QString::number(i++)] = item;
//    }
//    return o;
//}

int ItemsModel::indexOf(const Item& item) const
{
    assert(exist(item));

    int index = 0;
    auto it = _items.begin();
    auto id = idOf(item);
    while (idOf(it->second) != id)
        it++;
    return index;
}

unsigned long long ItemsModel::idOf(const Item& item)
{
    return item.id;
}

int ItemsModel::rowCount(const QModelIndex & parent) const
{
    return _items.size();
}

QVariant ItemsModel::data(const QModelIndex & qindex, int role /*= Qt::DisplayRole*/) const
{
    const auto &item = itemFromIndex(qindex.row());

    return item.toVariantMap();
}

const Item &ItemsModel::itemFromIndex(int index) const
{
    auto i = _items.cbegin();
    std::advance(i, index);
    return i->second;
}
